package com.binance.routing.hystrix;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Locale;

import javax.annotation.Resource;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.support.RequestContextUtils;

import com.alibaba.fastjson.JSON;
import com.binance.master.error.GeneralCode;
import com.binance.master.models.APIResponse;
import com.binance.master.utils.LogUtils;
import com.netflix.zuul.context.RequestContext;

@Component
public class AllFallback implements FallbackProvider {

  @Resource
  private MessageSource messageSource;

  @Override
  public String getRoute() {
    return "*";
  }

  @Override
  public ClientHttpResponse fallbackResponse() {
    RequestContext ctx = RequestContext.getCurrentContext();
    return this.fallbackResponse(ctx.getThrowable());
  }

  @Override
  public ClientHttpResponse fallbackResponse(Throwable cause) {
    LogUtils.warn("rout error:",cause);
    return new ClientHttpResponse() {

      @Override
      public HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        // 和body中的内容编码一致，否则容易乱码
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        return headers;
      }

      @Override
      public InputStream getBody() throws IOException {
        final RequestContext ctx = RequestContext.getCurrentContext();
        final Locale locale = RequestContextUtils.getLocale(ctx.getRequest());
        final APIResponse<?> errorResult = new APIResponse<>(APIResponse.Status.ERROR, APIResponse.Type.SYS,
            GeneralCode.SYS_ZUUL_ERROR.getCode(), getMessage(GeneralCode.SYS_ZUUL_ERROR, locale), null);
        return new ByteArrayInputStream(JSON.toJSONString(errorResult).getBytes("utf-8"));
      }

      @Override
      public String getStatusText() throws IOException {
        return HttpStatus.OK.getReasonPhrase();
      }

      @Override
      public HttpStatus getStatusCode() throws IOException {
        return HttpStatus.OK;
      }

      @Override
      public int getRawStatusCode() throws IOException {
        return HttpStatus.OK.value();
      }

      @Override
      public void close() {

      }
    };
  }

  private String getMessage(GeneralCode code, Locale locale, Object... params) {
    final StringBuffer key = new StringBuffer(code.getClass().getName());
    key.append(".");
    key.append(code);

    String msg = null;
    try {
      msg = this.messageSource.getMessage(new DefaultMessageSourceResolvable(key.toString()), locale);
      if (params != null) {
        msg = MessageFormat.format(msg, params);
      }
    } catch (NoSuchMessageException e) {
      msg = key.toString();
    }
    return msg;
  }

}
